package net.sk.china.city.config.component;

import cn.hutool.json.JSONUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import net.sk.china.city.constant.ImportMode;
import net.sk.china.city.domain.ArTeam;
import net.sk.china.city.domain.dto.excel.AddUser;
import net.sk.china.city.domain.dto.excel.ReadUser;
import net.sk.china.city.mapper.ArTeamMapper;
import net.sk.china.city.service.IUserService;
import net.sk.china.common.exception.ServiceException;
import net.sk.china.city.utils.PlatformIdHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class ExcelScanListener extends AnalysisEventListener<ReadUser> {
    // 数据集合
    private final IUserService userService;
    private final ImportMode importMode;
    public final Map<String, Long> teamNameIdMap = new HashMap<>();
    private final List<AddUser> addUserBuffer = new ArrayList<>();

    public ExcelScanListener(ArTeamMapper teamMapper, IUserService userService, ImportMode importMode) {
        this.userService = userService;
        this.importMode = importMode;
        List<ArTeam> teamList = teamMapper.selectAllTeamList(PlatformIdHolder.getPlatformId());
        System.out.println(JSONUtil.toJsonStr(teamList));
        for (ArTeam arTeam : teamList) {
            String teamName = arTeam.getTeamName();
            Long teamId = arTeam.getPkId();
            teamNameIdMap.put(teamName, teamId);
        }
    }

    // 每读取一行数据就会调用该方法
    @Override
    public void invoke(ReadUser readUser, AnalysisContext analysisContext) {
        checkField(readUser);
        AddUser addUser = readUsrToAddUser(readUser);
        addUserBuffer.add(addUser);
        // 每 batchCount 条数据，就将数据存入数据库中，并清空数据集合
        int batchCount = 20;
        if (addUserBuffer.size() >= batchCount) {
            saveData();
            addUserBuffer.clear();
        }
    }

    // 读取完整个 Excel 表格后就会调用该方法
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        log.info("所有数据解析完成！");
        saveData();
    }

    // 将数据存入数据库中
    public void saveData() {
        log.info("{}条数据，开始存储数据库！", addUserBuffer.size());
        //插入数据，相同手机号数据覆盖、数据库没有的手机号添加数据
        if (importMode == ImportMode.INCR)
            userService.insertUserBatch(addUserBuffer);
        else if (importMode == ImportMode.FULL)
            userService.fullInsertUserBatch(addUserBuffer);
    }

    private AddUser readUsrToAddUser(ReadUser readUser) {
        AddUser addUser = new AddUser();
        addUser.setIdNumber(readUser.getIdNumber());
        addUser.setRealName(readUser.getRealName());
        addUser.setAccount(readUser.getAccount());
        addUser.setWorkHours(readUser.getWorkHours());
        addUser.setPoint(readUser.getPoint());
        addUser.setTeamName(readUser.getTeamName());
        addUser.setRegionCode(readUser.getRegionCode());

        // 性别
        String sex = readUser.getSex();
        if (StringUtils.isEmpty(sex)) {
            addUser.setSex(2);
        } else if (sex.equals("男")) {
            addUser.setSex(0);
        } else if (sex.equals("女")) {
            addUser.setSex(1);
        }

        String birthDateStr = readUser.getIdNumber().substring(6, 14);
        LocalDate birthDate = LocalDate.parse(birthDateStr, DateTimeFormatter.ofPattern("yyyyMMdd"));
        addUser.setBirthDate(birthDate);

        // 志愿者队伍（查询队伍名称，然后设置队伍id）
        String teamName = readUser.getTeamName();
        if (StringUtils.isNotBlank(teamName)) {
            Long teamId = teamNameIdMap.get(teamName);
            addUser.setTeamId(teamId);
        }
        return addUser;
    }

    public void checkField(ReadUser readUser) {
        if (readUser == null) {
            throw new ServiceException("不能有空的一行");
        }
        String idNumber = readUser.getIdNumber();
        String realName = readUser.getRealName();
        String account = readUser.getAccount();
        BigDecimal workHours = readUser.getWorkHours();
        BigDecimal point = readUser.getPoint();
        String sex = readUser.getSex();
        // 空数据列校验
        if (StringUtils.isBlank(idNumber)
                || StringUtils.isBlank(realName)
                || StringUtils.isBlank(sex)
                || StringUtils.isBlank(account)
                || workHours == null
                || point == null
        ) {
            throw new ServiceException("不能出现为空的数据列");
        }
        // 生日、身份证校验
        if (idNumber.length() != 18) {
            throw new ServiceException("身份证号码长度不为18位，异常身份证号码：" + idNumber);
        }
        String birthDateStr = idNumber.substring(6, 14);
        try {
            LocalDate.parse(birthDateStr, DateTimeFormatter.ofPattern("yyyyMMdd"));
        } catch (Exception e) {
            throw new ServiceException("无法解析其生日，表格中有异常身份证号码：" + idNumber);
        }
    }
}
